from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QTextEdit, QLabel,
                             QPushButton, QScrollArea, QFrame, QMessageBox,
                             QDialog, QFormLayout, QLineEdit, QSpinBox,
                             QListWidget, QDialogButtonBox, QHBoxLayout,
                             QTabWidget, QComboBox, QToolBar, QStatusBar,
                             QMenu, QSizePolicy, QListWidgetItem)
from PyQt6.QtCore import Qt, QThread, pyqtSignal, QObject, QTimer
from PyQt6.QtGui import QPalette, QColor, QAction, QIcon, QTextCursor
import requests
import json
from question_bank import Question, QuestionBank
from learning_stats import LearningStatsManager
import os
from datetime import datetime
from ui.chat_panel import ChatPanel
import uuid

class AddQuestionDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("添加到题库")
        self.setModal(True)
        self.init_ui()
    
    def init_ui(self):
        layout = QFormLayout()
        self.setLayout(layout)
        
        # 知识点标签
        self.knowledge_tags = QListWidget()
        self.knowledge_tags.setSelectionMode(QListWidget.SelectionMode.MultiSelection)
        layout.addRow("知识点标签:", self.knowledge_tags)
        
        # 难度
        self.difficulty = QSpinBox()
        self.difficulty.setRange(1, 3)
        layout.addRow("难度:", self.difficulty)
        
        # 按钮
        buttons = QDialogButtonBox(
            QDialogButtonBox.StandardButton.Ok | 
            QDialogButtonBox.StandardButton.Cancel
        )
        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)
        layout.addRow(buttons)
    
    def get_tags(self):
        return [item.text() for item in self.knowledge_tags.selectedItems()]
    
    def get_difficulty(self):
        return self.difficulty.value()

class EditQuestionDialog(QDialog):
    def __init__(self, question: Question, parent=None):
        super().__init__(parent)
        self.question = question
        self.setWindowTitle("编辑题目")
        self.setModal(True)
        self.current_tags = set()  # 用于存储当前已添加的标签
        self.init_ui()
    
    def init_ui(self):
        layout = QFormLayout()
        self.setLayout(layout)
        
        # 题目内容
        self.question_edit = QTextEdit()
        self.question_edit.setText(self.question.question)
        layout.addRow("题目内容:", self.question_edit)
        
        # 答案
        self.answer_edit = QTextEdit()
        self.answer_edit.setText(self.question.answer)
        layout.addRow("答案:", self.answer_edit)
        
        # 标签输入区域
        tag_container = QWidget()
        tag_layout = QVBoxLayout()
        tag_container.setLayout(tag_layout)
        
        # 标签输入框
        self.tag_input = QLineEdit()
        self.tag_input.setPlaceholderText("输入标签，用逗号（中英文）分隔多个标签")
        self.tag_input.textChanged.connect(self.process_tags)  # 添加文本变化监听
        tag_layout.addWidget(self.tag_input)
        
        # 已添加的标签列表
        self.tag_list = QListWidget()
        self.tag_list.setSelectionMode(QListWidget.SelectionMode.MultiSelection)
        self.tag_list.itemDoubleClicked.connect(self.remove_tag)  # 双击删除标签
        tag_layout.addWidget(self.tag_list)
        
        # 添加已有标签
        if isinstance(self.question.tags, dict) and 'knowledge_tags' in self.question.tags:
            tags = self.question.tags['knowledge_tags']
            self.tag_input.setText(','.join(tags))  # 设置输入框文本
            for tag in tags:
                self.tag_list.addItem(tag)
                self.current_tags.add(tag)
        
        layout.addRow("知识点标签:", tag_container)
        
        # 难度
        self.difficulty = QSpinBox()
        self.difficulty.setRange(1, 3)
        self.difficulty.setValue(self.question.tags.get('difficulty', 1))
        layout.addRow("难度:", self.difficulty)
        
        # 按钮
        buttons = QDialogButtonBox(
            QDialogButtonBox.StandardButton.Ok | 
            QDialogButtonBox.StandardButton.Cancel
        )
        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)
        layout.addRow(buttons)
    
    def process_tags(self, text: str):
        """处理标签输入"""
        # 清空当前标签列表
        self.tag_list.clear()
        self.current_tags.clear()
        
        # 分割标签（支持中英文逗号）
        tags = [tag.strip() for tag in text.replace('，', ',').split(',') if tag.strip()]
        
        # 添加标签到列表
        for tag in tags:
            if tag not in self.current_tags:
                self.tag_list.addItem(tag)
                self.current_tags.add(tag)
    
    def remove_tag(self, item):
        """删除标签"""
        self.current_tags.remove(item.text())
        self.tag_list.takeItem(self.tag_list.row(item))
        # 更新输入框文本
        self.tag_input.setText(','.join(self.current_tags))
    
    def get_edited_question(self) -> Question:
        # 获取所有标签
        tags = list(self.current_tags)
        
        return Question(
            question=self.question_edit.toPlainText(),
            answer=self.answer_edit.toPlainText(),
            steps=self.question.steps,
            tags={
                "knowledge_tags": tags,
                "difficulty": self.difficulty.value()
            },
            is_favorite=self.question.is_favorite,
            last_review=self.question.last_review,
            review_count=self.question.review_count,
            correct_count=self.question.correct_count
        )

class AIWorker(QObject):
    finished = pyqtSignal(str)
    error = pyqtSignal(str)
    text_received = pyqtSignal(str, str)  # 修改为发送两个字符串：内容和标签
    
    def __init__(self, url, model, messages):
        super().__init__()
        self.url = url
        self.model = model
        self.messages = messages
        self.is_running = True
        self.current_content = ""  # 移到类属性
        self.current_tags = ""     # 移到类属性

    def run(self):
        try:
            # 重置内容
            self.current_content = ""
            self.current_tags = ""
            
            # 构建完整的对话历史
            data = {
                "model": self.model,
                "messages": self.messages,
                "stream": True,
                "options": {
                    "temperature": 0.7,
                    "top_p": 0.9,
                    "top_k": 40
                }
            }
            
            # 发送请求
            response = requests.post(self.url, json=data, stream=True, timeout=120)
            response.raise_for_status()
            
            # 处理流式响应
            in_tags = False
            tag_buffer = ""
            in_code_block = False
            code_block_content = ""
            
            for line in response.iter_lines():
                if not self.is_running:
                    break
                    
                if line:
                    try:
                        json_response = json.loads(line)
                        if 'message' in json_response and 'content' in json_response['message']:
                            text = json_response['message']['content']
                            
                            # 检查是否进入标签部分（两种格式）
                            if "###知识点标签" in text or "[TAGS]" in text:
                                in_tags = True
                                text = text.replace("###知识点标签", "").replace("[TAGS]", "").strip()
                                if text:
                                    tag_buffer = text
                                continue
                            
                            # 检查是否进入代码块
                            if "```" in text:
                                in_code_block = not in_code_block
                                if not in_code_block and code_block_content:  # 离开代码块时处理内容
                                    try:
                                        # 清理标签内容
                                        tag_content = code_block_content.replace("```json", "").replace("```", "").strip()
                                        # 尝试解析标签
                                        tags = json.loads(tag_content)
                                        if isinstance(tags, list):
                                            self.current_tags = json.dumps(tags)
                                            # 发送标签
                                            self.text_received.emit("", self.current_tags)
                                    except Exception as e:
                                        print(f"解析标签失败: {e}, 标签内容: {code_block_content}")
                                    code_block_content = ""
                                continue
                            
                            # 检查是否离开标签部分（格式2）
                            if "[/TAGS]" in text:
                                in_tags = False
                                try:
                                    # 清理标签内容
                                    tag_content = tag_buffer.strip()
                                    # 尝试解析标签
                                    tags = json.loads(tag_content)
                                    if isinstance(tags, list):
                                        self.current_tags = json.dumps(tags)
                                        # 发送标签
                                        self.text_received.emit("", self.current_tags)
                                except Exception as e:
                                    print(f"解析标签失败: {e}, 标签内容: {tag_buffer}")
                                tag_buffer = ""
                                continue
                            
                            # 在标签部分收集内容
                            if in_tags:
                                tag_buffer += text
                                continue
                            
                            # 在代码块中收集内容
                            if in_code_block:
                                code_block_content += text
                                continue
                            
                            # 发送普通内容
                            self.current_content += text
                            self.text_received.emit(text, "")
                            
                    except json.JSONDecodeError:
                        continue
                    except Exception as e:
                        print(f"处理响应时出错: {e}")
                        continue
            
            # 发送完成信号
            self.finished.emit(self.current_content)
            
        except Exception as e:
            self.error.emit(str(e))

    def stop(self):
        """停止处理"""
        self.is_running = False

class SaveQuestionDialog(QDialog):
    def __init__(self, question_content: str, answer_content: str, parent=None):
        super().__init__(parent)
        self.setWindowTitle("保存为题目")
        self.setModal(True)
        self.parent_widget = parent  # 保存父窗口引用
        self.current_tags = set()  # 用于存储当前已添加的标签
        self.init_ui(question_content, answer_content)
    
    def init_ui(self, question_content: str, answer_content: str):
        layout = QFormLayout()
        self.setLayout(layout)
        
        # 题目内容
        self.question_edit = QTextEdit()
        self.question_edit.setText(question_content)
        self.question_edit.setMinimumHeight(100)
        layout.addRow("题目内容:", self.question_edit)
        
        # 答案内容
        self.answer_edit = QTextEdit()
        self.answer_edit.setText(answer_content)
        self.answer_edit.setMinimumHeight(200)
        layout.addRow("答案内容:", self.answer_edit)
        
        # 标签输入区域
        tag_container = QWidget()
        tag_layout = QVBoxLayout()
        tag_container.setLayout(tag_layout)
        
        # 标签输入框
        self.tag_input = QLineEdit()
        self.tag_input.setPlaceholderText("输入标签，用逗号（中英文）分隔多个标签")
        self.tag_input.textChanged.connect(self.process_tags)  # 添加文本变化监听
        tag_layout.addWidget(self.tag_input)
        
        # 已添加的标签列表
        self.tag_list = QListWidget()
        self.tag_list.setSelectionMode(QListWidget.SelectionMode.MultiSelection)
        self.tag_list.itemDoubleClicked.connect(self.remove_tag)  # 双击删除标签
        tag_layout.addWidget(self.tag_list)
        
        # 获取父窗口中的标签
        if isinstance(self.parent_widget, MessageWidget):
            try:
                if self.parent_widget.tags:
                    print(f"SaveQuestionDialog 获取到标签: {self.parent_widget.tags}")
                    # 尝试解析标签
                    if isinstance(self.parent_widget.tags, str):
                        try:
                            # 尝试直接解析 JSON
                            tags_dict = json.loads(self.parent_widget.tags)
                            if isinstance(tags_dict, dict) and 'knowledge_tags' in tags_dict:
                                for tag in tags_dict['knowledge_tags']:
                                    if tag not in self.current_tags:
                                        self.tag_list.addItem(tag)
                                        self.current_tags.add(tag)
                        except json.JSONDecodeError:
                            # 如果不是 JSON 格式，尝试从文本中提取标签
                            if "###知识点标签" in self.parent_widget.tags:
                                try:
                                    # 提取标签部分
                                    tag_content = self.parent_widget.tags.split("###知识点标签")[1].strip()
                                    # 移除代码块标记
                                    tag_content = tag_content.replace("```json", "").replace("```", "").strip()
                                    # 解析标签
                                    tags = json.loads(tag_content)
                                    if isinstance(tags, list):
                                        for tag in tags:
                                            if tag not in self.current_tags:
                                                self.tag_list.addItem(tag)
                                                self.current_tags.add(tag)
                                except Exception as e:
                                    print(f"从文本提取标签失败: {e}")
            except Exception as e:
                print(f"加载已有标签失败: {e}")
        
        layout.addRow("知识点标签:", tag_container)
        
        # 难度
        self.difficulty = QSpinBox()
        self.difficulty.setRange(1, 3)
        self.difficulty.setValue(1)
        layout.addRow("难度:", self.difficulty)
        
        # 按钮
        buttons = QDialogButtonBox(
            QDialogButtonBox.StandardButton.Ok | 
            QDialogButtonBox.StandardButton.Cancel
        )
        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)
        layout.addRow(buttons)
    
    def process_tags(self, text: str):
        """处理标签输入"""
        # 清空当前标签列表
        self.tag_list.clear()
        self.current_tags.clear()
        
        # 分割标签（支持中英文逗号）
        tags = [tag.strip() for tag in text.replace('，', ',').split(',') if tag.strip()]
        
        # 添加标签到列表
        for tag in tags:
            if tag not in self.current_tags:
                self.tag_list.addItem(tag)
                self.current_tags.add(tag)
    
    def remove_tag(self, item):
        """删除标签"""
        self.current_tags.remove(item.text())
        self.tag_list.takeItem(self.tag_list.row(item))
        # 更新输入框文本
        self.tag_input.setText(','.join(self.current_tags))
    
    def get_question_data(self):
        # 格式化题目和答案
        question = self.question_edit.toPlainText().strip()
        answer = self.answer_edit.toPlainText().strip()
        
        # 获取所有标签
        tags = list(self.current_tags)
        
        return {
            "question": question,
            "answer": answer,
            "tags": {
                "knowledge_tags": tags,
                "difficulty": self.difficulty.value()
            }
        }

class MessageWidget(QFrame):
    def __init__(self, content: str, is_user: bool = True, parent=None):
        super().__init__(parent)
        self.is_user = is_user
        self.tags = None  # 初始化标签属性
        self.init_ui(content)
    
    def init_ui(self, content: str):
        # 主布局
        layout = QVBoxLayout()
        layout.setContentsMargins(8, 8, 8, 8)
        self.setLayout(layout)
        
        # 文本标签
        self.text_label = QLabel(content)
        self.text_label.setWordWrap(True)
        self.text_label.setTextFormat(Qt.TextFormat.RichText)
        self.text_label.setOpenExternalLinks(True)
        self.text_label.setStyleSheet("""
            QLabel {
                color: #E0E0E0;
                font-size: 14px;
                line-height: 1.5;
                padding: 8px;
                border-radius: 4px;
                background-color: #2D2D2D;
            }
        """)
        layout.addWidget(self.text_label)
        
        # 设置样式
        self.setStyleSheet("""
            MessageWidget {
                background-color: #2D2D2D;
                border-radius: 8px;
                margin: 4px 0;
            }
        """)
        
        # 设置大小策略
        self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
        
        # 计算并设置高度
        self._calculate_and_set_height()
        
        # 启用鼠标追踪
        self.setMouseTracking(True)
        
        # 设置右键菜单
        self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
        self.customContextMenuRequested.connect(self.show_context_menu)
    
    def on_double_click(self, event):
        """处理双击事件"""
        if event.button() == Qt.MouseButton.LeftButton:
            # 显示题目详情
            right_panel = self.get_right_panel()
            if right_panel and right_panel.current_question:
                right_panel.show_question_detail(right_panel.current_question)
    
    def _calculate_and_set_height(self):
        """计算并设置高度"""
        # 获取文本内容的高度
        text_height = self.text_label.sizeHint().height()
        # 设置最小高度
        self.setMinimumHeight(text_height + 16)  # 16是上下边距
    
    def append_text(self, text: str, tags: str = ""):
        """追加文本内容"""
        try:
            # 追加文本
            current_text = self.text_label.text()
            self.text_label.setText(current_text + text)
            
            # 处理标签
            if tags:
                self.set_tags(tags)
            
            # 重新计算高度
            self._calculate_and_set_height()
            
        except Exception as e:
            print(f"追加文本失败: {e}")
    
    def show_context_menu(self, pos):
        """显示右键菜单"""
        menu = QMenu(self)
        
        # 保存为题目
        save_action = QAction("保存为题目", self)
        save_action.triggered.connect(self.save_as_question)
        menu.addAction(save_action)
        
        # 删除题目
        delete_action = QAction("删除题目", self)
        delete_action.triggered.connect(self.delete_question)
        menu.addAction(delete_action)
        
        menu.exec(self.mapToGlobal(pos))
    
    def get_right_panel(self):
        """获取父窗口（RightPanel）"""
        parent = self.parent()
        while parent:
            if isinstance(parent, RightPanel):
                return parent
            parent = parent.parent()
        return None
    
    def save_as_question(self):
        """保存为题目"""
        try:
            # 获取父窗口（RightPanel）
            right_panel = self.get_right_panel()
            if not right_panel:
                return
            
            # 获取当前消息的内容
            if self.is_user:  # 当前是用户消息
                # 查找对应的AI回答
                ai_message = None
                for i in range(self.parent().layout().count()):
                    widget = self.parent().layout().itemAt(i).widget()
                    if isinstance(widget, MessageWidget) and not widget.is_user:
                        ai_message = widget
                        break
                
                if ai_message:
                    question_content = self.text_label.text()
                    answer_content = ai_message.text_label.text()
                    answer_tags = ai_message.tags
                    print(f"获取到AI回答的标签: {answer_tags}")  # 调试输出
                else:
                    QMessageBox.warning(self, "警告", "没有对应的AI回答")
                    return
            else:  # 当前是AI消息
                answer_content = self.text_label.text()
                answer_tags = self.tags
                # 查找对应的用户问题
                user_message = None
                for i in range(self.parent().layout().count()):
                    widget = self.parent().layout().itemAt(i).widget()
                    if isinstance(widget, MessageWidget) and widget.is_user:
                        user_message = widget
                        break
                
                if user_message:
                    question_content = user_message.text_label.text()
                else:
                    QMessageBox.warning(self, "警告", "没有对应的用户问题")
                    return
            
            # 显示保存对话框
            dialog = SaveQuestionDialog(question_content, answer_content, self)
            if dialog.exec() == QDialog.DialogCode.Accepted:
                # 获取保存的数据
                question_data = dialog.get_question_data()
                
                # 添加标签
                if answer_tags:
                    try:
                        tags = json.loads(answer_tags)
                        if isinstance(tags, list):
                            question_data['tags']['knowledge_tags'].extend(tags)
                    except Exception as e:
                        print(f"解析标签失败: {e}")
                
                # 添加到题库
                right_panel.question_bank.add_question(question_data)
                right_panel.status_bar.showMessage("题目已保存")
        
        except Exception as e:
            QMessageBox.critical(self, "错误", f"保存题目时出错: {str(e)}")
    
    def delete_question(self):
        """删除当前题目"""
        try:
            # 获取父窗口（RightPanel）
            right_panel = self.get_right_panel()
            if not right_panel or not right_panel.current_question:
                return
            
            # 确认删除
            reply = QMessageBox.question(
                self, "确认删除",
                "确定要删除这道题目吗？",
                QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
                QMessageBox.StandardButton.No
            )
            
            if reply == QMessageBox.StandardButton.Yes:
                # 获取当前题目的索引
                current_index = -1
                for i, q in enumerate(right_panel.question_bank.questions):
                    if q.get('id') == right_panel.current_question.id:
                        current_index = i
                        break
                
                if current_index != -1:
                    # 删除题目
                    right_panel.question_bank.delete_question(current_index)
                    # 清空当前对话
                    right_panel._clear_chat()
                    # 更新状态栏
                    right_panel.status_bar.showMessage("题目已删除")
                else:
                    QMessageBox.warning(self, "警告", "无法找到要删除的题目")
        
        except Exception as e:
            QMessageBox.critical(self, "错误", f"删除题目时出错: {str(e)}")
    
    def resizeEvent(self, event):
        """处理大小改变事件"""
        super().resizeEvent(event)
        # 确保文本标签宽度正确
        self.text_label.setMinimumWidth(self.width() - 24)
        self._calculate_and_set_height()
    
    def set_tags(self, tags):
        """设置标签"""
        try:
            print(f"MessageWidget set_tags 收到标签: {tags}")  # 调试输出
            # 尝试解析 JSON 格式
            if isinstance(tags, str):
                # 检查是否是 [TAGS] 格式
                if "[TAGS]" in tags:
                    try:
                        # 提取标签部分
                        tag_content = tags.split("[TAGS]")[1].split("[/TAGS]")[0].strip()
                        print(f"MessageWidget 提取的标签内容: {tag_content}")  # 调试输出
                        # 尝试解析标签内容
                        parsed_tags = json.loads(tag_content)
                        if isinstance(parsed_tags, list):
                            self.tags = json.dumps({"knowledge_tags": parsed_tags})
                            print(f"MessageWidget 设置标签成功: {self.tags}")  # 调试输出
                            return
                    except (json.JSONDecodeError, IndexError) as e:
                        print(f"MessageWidget 解析标签失败: {e}")  # 调试输出
                
                # 尝试直接解析 JSON 格式
                try:
                    tags_dict = json.loads(tags)
                    if isinstance(tags_dict, dict):
                        self.tags = json.dumps(tags_dict)
                        print(f"MessageWidget 设置标签成功: {self.tags}")  # 调试输出
                        return
                except json.JSONDecodeError as e:
                    print(f"MessageWidget 解析JSON失败: {e}")  # 调试输出
                
                # 尝试解析 [tag1, tag2] 格式
                if tags.startswith('[') and tags.endswith(']'):
                    try:
                        tags_list = json.loads(tags)
                        if isinstance(tags_list, list):
                            self.tags = json.dumps({"knowledge_tags": tags_list})
                            print(f"MessageWidget 设置标签成功: {self.tags}")  # 调试输出
                            return
                    except json.JSONDecodeError as e:
                        print(f"MessageWidget 解析数组失败: {e}")  # 调试输出
            
            # 如果都不是，保持原样
            self.tags = tags
            print(f"MessageWidget 保持原标签: {self.tags}")  # 调试输出
        except Exception as e:
            print(f"MessageWidget 设置标签失败: {e}")
            self.tags = None

class RightPanel(QWidget):
    def __init__(self, question_bank=None):
        super().__init__()
        self.question_bank = question_bank or QuestionBank()
        self.current_question = None
        self.current_question_index = -1
        self.current_message_widget = None  # 初始化消息组件
        self.learning_stats = LearningStatsManager()  # 初始化学习统计管理器
        self.init_ui()
        self.setup_styles()
        
        # AI相关设置
        self.ollama_url = "http://localhost:11434/api/generate"  # 使用 generate API
        self.current_model = "qwen2.5:7b"
        
        # 线程相关
        self.thread = None
        self.worker = None
        self.is_processing = False
        
        # 初始化标签列表
        # self.update_tag_list()
    
    def init_ui(self):
        # 主布局
        main_layout = QHBoxLayout()  # 改为水平布局
        main_layout.setContentsMargins(0, 0, 0, 0)
        main_layout.setSpacing(0)
        self.setLayout(main_layout)
        
        # 右侧聊天区域
        right_panel = QWidget()
        right_layout = QVBoxLayout()
        right_panel.setLayout(right_layout)
        
        # 工具栏
        toolbar = QToolBar()
        toolbar.setFixedHeight(40)
        toolbar.setStyleSheet("""
            QToolBar {
                background-color: #2D2D2D;
                border-bottom: 1px solid #404040;
                padding: 0 8px;
            }
        """)
        
        # 模型选择
        self.model_combo = QComboBox()
        self.model_combo.addItems(["qwen2.5:7b", "llama2:7b", "mistral:7b"])
        self.model_combo.setFixedHeight(28)
        self.model_combo.currentTextChanged.connect(self.set_model)
        toolbar.addWidget(QLabel("模型："))
        toolbar.addWidget(self.model_combo)
        
        toolbar.addSeparator()
        
        # 清空对话
        self.clear_action = QAction("清空对话", self)
        self.clear_action.triggered.connect(self.clear_chat)
        toolbar.addAction(self.clear_action)
        
        # 学习统计
        self.stats_action = QAction("学习统计", self)
        self.stats_action.triggered.connect(self.show_learning_stats)
        toolbar.addAction(self.stats_action)
        
        right_layout.addWidget(toolbar)
        
        # 聊天记录区域
        self.chat_area = QScrollArea()
        self.chat_area.setWidgetResizable(True)
        self.chat_area.setStyleSheet("""
            QScrollArea {
                border: none;
                background-color: #1E1E1E;
            }
            QScrollBar:vertical {
                border: none;
                background-color: #2D2D2D;
                width: 8px;
                margin: 0px;
            }
            QScrollBar::handle:vertical {
                background-color: #404040;
                min-height: 20px;
                border-radius: 4px;
            }
            QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
                height: 0px;
            }
            QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
                background: none;
            }
        """)
        
        # 聊天内容容器
        self.chat_widget = QWidget()
        self.chat_widget.setStyleSheet("""
            QWidget {
                background-color: #1E1E1E;
            }
        """)
        self.chat_layout = QVBoxLayout()
        self.chat_layout.setContentsMargins(8, 8, 8, 8)
        self.chat_layout.setSpacing(8)
        self.chat_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
        self.chat_widget.setLayout(self.chat_layout)
        self.chat_area.setWidget(self.chat_widget)
        right_layout.addWidget(self.chat_area, stretch=1)
        
        # 输入区域
        input_container = QFrame()
        input_container.setStyleSheet("""
            QFrame {
                background-color: #2D2D2D;
                border-top: 1px solid #404040;
            }
        """)
        input_layout = QHBoxLayout()
        input_layout.setContentsMargins(8, 4, 8, 4)
        input_layout.setSpacing(8)
        input_container.setLayout(input_layout)
        
        # 输入框
        self.input_box = QTextEdit()
        self.input_box.setPlaceholderText("输入问题... (按Enter发送，Ctrl+Enter换行)")
        self.input_box.setMaximumHeight(36)
        self.input_box.setMinimumHeight(36)
        self.input_box.setStyleSheet("""
            QTextEdit {
                background-color: #1E1E1E;
                border: 1px solid #404040;
                border-radius: 4px;
                padding: 4px 8px;
                color: #FFFFFF;
                font-size: 14px;
                line-height: 1.4;
            }
        """)
        self.input_box.textChanged.connect(self.adjust_input_height)
        self.input_box.installEventFilter(self)
        input_layout.addWidget(self.input_box, stretch=1)
        
        # 发送按钮
        self.send_button = QPushButton("发送")
        self.send_button.setFixedSize(64, 28)
        self.send_button.clicked.connect(self.send_message)
        input_layout.addWidget(self.send_button)
        
        right_layout.addWidget(input_container)
        
        # 状态栏
        self.status_bar = QStatusBar()
        self.status_bar.setFixedHeight(24)
        self.status_bar.setStyleSheet("""
            QStatusBar {
                background-color: #2D2D2D;
                border-top: 1px solid #404040;
                padding: 0 8px;
            }
        """)
        right_layout.addWidget(self.status_bar)
        self.status_bar.showMessage("就绪")
        
        main_layout.addWidget(right_panel, stretch=1)
    
    def update_tag_list(self):
        """更新标签列表"""
        try:
            self.tag_list.clear()
            
            # 获取所有标签及其正确率
            tag_stats = {}
            for question in self.question_bank.questions:
                if isinstance(question.get('tags', {}).get('knowledge_tags'), list):
                    for tag in question['tags']['knowledge_tags']:
                        if tag not in tag_stats:
                            tag_stats[tag] = {
                                'total': 0,
                                'correct': 0
                            }
                        tag_stats[tag]['total'] += 1
                        if question.get('correct_count', 0) > 0:
                            tag_stats[tag]['correct'] += 1
            
            # 计算每个标签的正确率并排序
            sorted_tags = []
            for tag, stats in tag_stats.items():
                accuracy = stats['correct'] / stats['total'] if stats['total'] > 0 else 0
                sorted_tags.append((tag, accuracy, stats['total']))
            
            # 按正确率降序排序
            sorted_tags.sort(key=lambda x: (-x[1], -x[2]))
            
            # 添加到列表
            for tag, accuracy, total in sorted_tags:
                item = QListWidgetItem(f"{tag} ({accuracy:.0%}, {total}题)")
                item.setData(Qt.ItemDataRole.UserRole, tag)  # 存储原始标签
                self.tag_list.addItem(item)
            
        except Exception as e:
            print(f"更新标签列表失败: {e}")
    
    def on_tag_clicked(self, item):
        """处理标签点击事件"""
        try:
            tag = item.data(Qt.ItemDataRole.UserRole)
            if tag:
                # 获取包含该标签的题目
                questions = []
                for q in self.question_bank.questions:
                    if isinstance(q.get('tags', {}).get('knowledge_tags'), list):
                        if tag in q['tags']['knowledge_tags']:
                            # 创建 Question 对象，只传入必要的参数
                            question = Question(
                                id=q.get('id'),
                                question=q.get('question', ''),
                                answer=q.get('answer', ''),
                                steps=q.get('steps', []),
                                tags=q.get('tags', {'knowledge_tags': []}),
                                is_favorite=q.get('is_favorite', False),
                                last_review_date=q.get('last_review_date'),
                                review_count=q.get('review_count', 0),
                                correct_count=q.get('correct_count', 0),
                                mastery_level=q.get('mastery_level', 0.0)
                            )
                            questions.append(question)
                
                if questions:
                    # 显示第一个题目
                    self.load_question(questions[0])
        except Exception as e:
            print(f"处理标签点击事件失败: {e}")
            QMessageBox.critical(self, "错误", f"加载题目失败: {str(e)}")
    
    def _format_steps(self, steps):
        """格式化解题步骤"""
        if not steps:
            return "暂无解题步骤"
            
        formatted_steps = []
        for i, step in enumerate(steps, 1):
            if isinstance(step, dict):
                step_text = f"步骤 {i}：{step.get('step', step.get('content', ''))}\n"
                tags = step.get('tags', {})
                if isinstance(tags, dict):
                    if 'known' in tags:
                        step_text += f"已知条件：{tags['known']}\n"
                    if 'goal' in tags:
                        step_text += f"目标：{tags['goal']}\n"
                    if 'thinking' in tags:
                        step_text += f"思考过程：{tags['thinking']}\n"
                    if 'reason' in tags:
                        step_text += f"原因：{tags['reason']}\n"
                    if 'error_analysis' in tags:
                        step_text += f"错误分析：{tags['error_analysis']}\n"
            else:
                step_text = f"步骤 {i}：{str(step)}\n"
            formatted_steps.append(step_text)
        return "\n".join(formatted_steps)
    
    def set_model(self, model_name: str):
        """设置要使用的Ollama模型"""
        self.current_model = model_name
        self.status_bar.showMessage(f"已切换到模型：{model_name}")
    
    def export_chat(self):
        """导出对话历史"""
        if not self.conversation_history:
            QMessageBox.warning(self, "警告", "没有可导出的对话历史")
            return
        
        try:
            # 创建导出目录
            export_dir = "exports"
            if not os.path.exists(export_dir):
                os.makedirs(export_dir)
            
            # 生成文件名
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            filename = f"{export_dir}/chat_{timestamp}.json"
            
            # 导出对话历史
            with open(filename, 'w', encoding='utf-8') as f:
                json.dump(self.conversation_history, f, ensure_ascii=False, indent=2)
            
            QMessageBox.information(self, "成功", f"对话历史已导出到：{filename}")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"导出失败：{str(e)}")
    
    def add_message(self, content: str, is_user: bool = True):
        """添加消息"""
        try:
            message = MessageWidget(content, is_user, self.chat_widget)
            self.chat_layout.addWidget(message)
            self._refresh_chat_area()
        except Exception as e:
            print(f"添加消息时出错: {e}")
    
    def _refresh_chat_area(self):
        """刷新聊天区域高度并滚动到底部"""
        # 只更新最后一个消息框的高度
        if self.chat_layout.count() > 0:
            last_widget = self.chat_layout.itemAt(self.chat_layout.count() - 1).widget()
            if isinstance(last_widget, MessageWidget):
                last_widget._calculate_and_set_height()
        
        # 更新布局
        self.chat_widget.adjustSize()
        self.chat_widget.updateGeometry()
        
        # 使用定时器确保滚动到底部
        QTimer.singleShot(100, lambda: self.chat_area.verticalScrollBar().setValue(
            self.chat_area.verticalScrollBar().maximum()
        ))
    
    def adjust_input_height(self):
        """根据内容调整输入框高度"""
        doc_height = self.input_box.document().size().height()
        new_height = min(max(doc_height + 8, 36), 120)  # 最大高度120px
        self.input_box.setMaximumHeight(int(new_height))
    
    def eventFilter(self, obj, event):
        """事件过滤器，处理输入框的按键事件"""
        if obj == self.input_box and event.type() == event.Type.KeyPress:
            if event.key() == Qt.Key.Key_Return:
                if event.modifiers() == Qt.KeyboardModifier.ControlModifier:
                    # Ctrl+Enter 换行
                    return False
                else:
                    # Enter 发送消息
                    self.send_message()
                    return True
        return super().eventFilter(obj, event)
    
    def send_message(self):
        """发送消息"""
        if self.is_processing:
            self.status_bar.showMessage("正在处理上一个请求，请稍候...")
            return
            
        message = self.input_box.toPlainText().strip()
        if not message:
            return
        
        try:
            # 显示用户消息
            self.add_message(message, True)
            self.input_box.clear()
            
            # 如果是普通对话，添加标签生成的要求
            if not self.current_question:
                message += """
请在回答的最后，用以下格式添加知识点标签（二选一）：

格式1：
###知识点标签
```json
["知识点1", "知识点2", "知识点3"]
```

格式2：
[TAGS]
["知识点1", "知识点2", "知识点3"]
[/TAGS]

注意：
- 标签应该是具体的知识点，与问题直接相关
- 标签数量建议3-5个
- 标签必须是JSON数组格式
"""
            
            # 准备发送给AI的消息
            messages = [{"role": "user", "content": message}]
        
            # 发送消息到AI
            self.send_to_ai(messages)
            
        except Exception as e:
            print(f"发送消息时出错: {e}")
            QMessageBox.critical(self, "错误", f"发送消息时出错: {str(e)}")
    
    def send_to_ai(self, messages):
        """发送消息到AI"""
        if self.is_processing:
            self.status_bar.showMessage("正在处理上一个请求，请稍候...")
            return
            
        try:
            self.is_processing = True
            self.status_bar.showMessage("正在等待AI响应...")
            
            # 清理之前的线程
            self.cleanup_thread()
            
            # 创建新的工作线程
            self.thread = QThread()
            self.worker = AIWorker(self.ollama_url, self.current_model, messages)
            
            # 移动worker到线程
            self.worker.moveToThread(self.thread)
            
            # 连接信号
            self.thread.started.connect(self.worker.run)
            self.worker.text_received.connect(self.on_text_received)
            self.worker.finished.connect(self.on_stream_finished)
            self.worker.error.connect(self.on_ai_error)
            
            # 连接清理信号
            self.worker.finished.connect(self.thread.quit)
            self.worker.error.connect(self.thread.quit)
            self.thread.finished.connect(self.thread.deleteLater)
            self.thread.finished.connect(self.on_thread_finished)
            
            # 启动线程
            self.thread.start()
            
        except Exception as e:
            print(f"启动AI响应时出错: {e}")
            self.on_ai_error(str(e))
            self.is_processing = False
    
    def cleanup_thread(self):
        """清理线程资源"""
        try:
            if self.worker:
                self.worker.stop()
            if self.thread and self.thread.isRunning():
                self.thread.quit()
                self.thread.wait()
            self.current_message_widget = None
        except Exception as e:
            print(f"清理线程资源时出错: {e}")
    
    def on_text_received(self, text, tags=""):
        """处理接收到的文本"""
        try:
            if self.current_message_widget is None:
                self.current_message_widget = MessageWidget("", False, self.chat_widget)
                self.chat_layout.addWidget(self.current_message_widget)
            self.current_message_widget.append_text(text, tags)
            self._refresh_chat_area()
        except Exception as e:
            print(f"处理接收到的文本时出错: {e}")
            self.current_message_widget = None
    
    def on_stream_finished(self):
        """流式传输完成"""
        try:
            self.current_message_widget = None
            self.is_processing = False
            self.status_bar.showMessage("就绪")
        except Exception as e:
            print(f"流式传输完成处理时出错: {e}")
    
    def on_ai_error(self, error_msg: str):
        """处理AI错误"""
        self.add_message(f"错误：{error_msg}", False)
        self.is_processing = False
        self.status_bar.showMessage("发生错误")
    
    def on_thread_finished(self):
        """线程完成时的处理"""
        self.worker = None
        self.thread = None
    
    def resizeEvent(self, event):
        """处理窗口大小改变事件"""
        super().resizeEvent(event)
        for i in range(self.chat_layout.count()):
            widget = self.chat_layout.itemAt(i).widget()
            if isinstance(widget, MessageWidget):
                widget.setMaximumWidth(self.chat_widget.width() - 40)
        self._refresh_chat_area()

    def show_question_detail(self, question: Question):
        """显示题目详情"""
        dialog = QuestionDetailDialog(question, self.question_bank, self)
        dialog.exec()

    def show_learning_stats(self):
        """显示学习统计"""
        # 更新当前题目的学习统计
        if self.current_question and self.current_question.id:
            # 更新题目统计
            self.learning_stats.update_question_stats(
                self.current_question.id,
                self.current_question.correct_count > 0,
                self.current_question.wrong_steps
            )
            
            # 更新知识点统计
            if isinstance(self.current_question.tags, dict) and 'knowledge_tags' in self.current_question.tags:
                self.learning_stats.update_knowledge_stats(
                    self.current_question.id,
                    self.current_question.tags['knowledge_tags']
                )
            
            # 更新难度统计
            if isinstance(self.current_question.tags, dict) and 'difficulty' in self.current_question.tags:
                self.learning_stats.update_difficulty_stats(
                    self.current_question.id,
                    self.current_question.tags['difficulty']
                )
        
        # 获取学习分析报告
        report = self.learning_stats.get_learning_analysis()
        
        # 构建提示词
        prompt = f"""请根据以下学习统计数据，分析我的学习情况，并给出具体的改进建议：

{report}

请从以下几个方面进行分析：
1. 学习效果评估
2. 知识掌握情况
3. 学习习惯分析
4. 具体改进建议
5. 学习计划建议

请用中文回答，并给出具体的、可执行的建议。"""
        
        # 显示统计报告
        dialog = QDialog(self)
        dialog.setWindowTitle("学习统计")
        dialog.setMinimumSize(600, 400)
        
        layout = QVBoxLayout()
        dialog.setLayout(layout)
        
        # 统计报告
        report_text = QTextEdit()
        report_text.setReadOnly(True)
        report_text.setText(report)
        layout.addWidget(report_text)
        
        # AI分析按钮
        analyze_button = QPushButton("获取AI分析")
        analyze_button.clicked.connect(lambda: self.get_ai_analysis(prompt))
        layout.addWidget(analyze_button)
        
        dialog.exec()
    
    def get_ai_analysis(self, prompt: str):
        """获取AI分析"""
        try:
            # 准备发送给AI的完整对话历史
            messages = [{"role": "user", "content": prompt}]
            
            # 发送消息到AI
            self.send_to_ai(messages)
            
        except Exception as e:
            print(f"获取AI分析时出错: {e}")
            QMessageBox.critical(self, "错误", f"获取AI分析时出错: {str(e)}")

    def _switch_question(self, new_index: int):
        """切换题目"""
        if not self.question_bank or new_index < 0 or new_index >= len(self.question_bank.questions):
            return
            
        # 清空当前对话
        self._clear_chat()
        
        # 加载新题目
        new_question = self.question_bank.questions[new_index]
        self.current_question = new_question
        self.current_question_index = new_index
        
        # 更新学习统计
        if new_question.id:
            # 更新题目统计
            self.learning_stats.update_question_stats(
                new_question.id,
                new_question.correct_count > 0,
                new_question.wrong_steps
            )
            
            # 更新知识点统计
            if isinstance(new_question.tags, dict) and 'knowledge_tags' in new_question.tags:
                self.learning_stats.update_knowledge_stats(
                    new_question.id,
                    new_question.tags['knowledge_tags']
                )
            
            # 更新难度统计
            if isinstance(new_question.tags, dict) and 'difficulty' in new_question.tags:
                self.learning_stats.update_difficulty_stats(
                    new_question.id,
                    new_question.tags['difficulty']
                )
        
        # 构建提示词
        prompt = f"""请帮我分析这道题目：

题目：{new_question.question}

答案：{new_question.answer}

解题步骤：
{self._format_steps(new_question.steps)}

请帮我：
1. 分析题目的关键点
2. 总结相关知识点
3. 在回答的最后，请用以下格式添加知识点标签：
###知识点标签
```json
["知识点1", "知识点2", "知识点3"]
```

注意：
- 标签应该是具体的知识点，而不是笼统的分类
- 标签应该与题目内容直接相关
- 标签数量建议在3-5个
- 标签格式必须是JSON数组格式
"""
        
        # 自动发送到AI
        self.input_box.setText(prompt)
        self.send_message()

    def _clear_chat(self):
        """清空对话历史（内部方法）"""
        # 清空输入框
        self.input_box.clear()
        
        # 清空当前消息组件
        self.current_message_widget = None
        
        # 清空聊天记录
        while self.chat_layout.count():
            item = self.chat_layout.takeAt(0)
            if item.widget():
                item.widget().deleteLater()
        
        # 更新状态栏
        self.status_bar.showMessage("对话已清空")
        
        # 强制更新界面
        self.chat_widget.update()
        self.chat_area.viewport().update()
    
    def clear_chat(self):
        """清空对话历史（公共方法）"""
        self._clear_chat()
    
    def closeEvent(self, event):
        """窗口关闭时清理资源"""
        self.cleanup_thread()
        super().closeEvent(event) 

    def setup_styles(self):
        """设置样式"""
        self.setStyleSheet("""
            QWidget {
                background-color: #1E1E1E;
                color: #FFFFFF;
            }
            QTextEdit {
                background-color: #2D2D2D;
                border: 1px solid #404040;
                border-radius: 4px;
                padding: 8px;
                color: #FFFFFF;
            }
            QPushButton {
                background-color: #2196F3;
                color: #FFFFFF;
                border: none;
                border-radius: 4px;
                padding: 8px 16px;
            }
            QPushButton:hover {
                background-color: #1976D2;
            }
            QPushButton:pressed {
                background-color: #1565C0;
            }
            QScrollArea {
                border: none;
                background-color: transparent;
            }
        """)

    def load_question(self, question: Question, index: int = -1, conversation_history: list = None):
        """加载题目并初始化对话"""
        try:
            # 先清空当前对话
            self._clear_chat()
            
            # 设置新题目
            self.current_question = question
            self.current_question_index = index
            
            # 更新学习统计
            if question.id:
                # 更新题目统计
                self.learning_stats.update_question_stats(
                    question.id,
                    question.correct_count > 0,
                    question.wrong_steps
                )
                
                # 更新知识点统计
                if isinstance(question.tags, dict) and 'knowledge_tags' in question.tags:
                    self.learning_stats.update_knowledge_stats(
                        question.id,
                        question.tags['knowledge_tags']
                    )
                
                # 更新难度统计
                if isinstance(question.tags, dict) and 'difficulty' in question.tags:
                    self.learning_stats.update_difficulty_stats(
                        question.id,
                        question.tags['difficulty']
                    )
            
            # 启用输入框并设置提示文本
            self.input_box.setEnabled(True)
            self.input_box.setPlaceholderText("输入您的问题...")
            
            # 显示题目内容
            self.add_message(f"题目：{question.question}\n\n答案：{question.answer}", False)
            
        except Exception as e:
            print(f"加载题目时出错: {e}")
            QMessageBox.critical(self, "错误", f"加载题目时出错: {str(e)}")

class QuestionDetailDialog(QDialog):
    def __init__(self, question: Question, question_bank: QuestionBank, parent=None):
        super().__init__(parent)
        self.question = question
        self.question_bank = question_bank
        self.current_index = question_bank.questions.index(question)
        self.right_panel = parent  # 保存 RightPanel 引用
        self.init_ui()
    
    def init_ui(self):
        layout = QVBoxLayout()
        self.setLayout(layout)
        
        # 题目内容
        question_label = QLabel(f"题目：{self.question.question}")
        question_label.setWordWrap(True)
        layout.addWidget(question_label)
        
        # 答案
        answer_label = QLabel(f"答案：{self.question.answer}")
        answer_label.setWordWrap(True)
        layout.addWidget(answer_label)
        
        # 标签
        if isinstance(self.question.tags, dict) and 'knowledge_tags' in self.question.tags:
            tags = self.question.tags['knowledge_tags']
            tags_label = QLabel(f"标签：{', '.join(tags)}")
            tags_label.setWordWrap(True)
            layout.addWidget(tags_label)
        
        # 难度
        difficulty = self.question.tags.get('difficulty', 1)
        difficulty_label = QLabel(f"难度：{difficulty}")
        layout.addWidget(difficulty_label)
        
        # 按钮区域
        button_layout = QHBoxLayout()
        
        # 上一题按钮
        self.prev_button = QPushButton("上一题")
        self.prev_button.clicked.connect(self.prev_question)
        self.prev_button.setEnabled(self.current_index > 0)
        button_layout.addWidget(self.prev_button)
        
        # 下一题按钮
        self.next_button = QPushButton("下一题")
        self.next_button.clicked.connect(self.next_question)
        self.next_button.setEnabled(self.current_index < len(self.question_bank.questions) - 1)
        button_layout.addWidget(self.next_button)
        
        # 编辑按钮
        edit_button = QPushButton("编辑")
        edit_button.clicked.connect(self.edit_question)
        button_layout.addWidget(edit_button)
        
        # 删除按钮
        delete_button = QPushButton("删除")
        delete_button.clicked.connect(self.delete_question)
        button_layout.addWidget(delete_button)
        
        layout.addLayout(button_layout)
    
    def prev_question(self):
        """切换到上一题"""
        if self.current_index > 0:
            # 调用 RightPanel 的 _switch_question 方法
            if isinstance(self.right_panel, RightPanel):
                self.right_panel._switch_question(self.current_index - 1)
            self.close()
    
    def next_question(self):
        """切换到下一题"""
        if self.current_index < len(self.question_bank.questions) - 1:
            # 调用 RightPanel 的 _switch_question 方法
            if isinstance(self.right_panel, RightPanel):
                self.right_panel._switch_question(self.current_index + 1)
            self.close()
    
    def edit_question(self):
        """编辑题目"""
        dialog = EditQuestionDialog(self.question, self)
        if dialog.exec() == QDialog.DialogCode.Accepted:
            edited_question = dialog.get_edited_question()
            # 更新题目
            self.question_bank.update_question(edited_question)
            # 刷新显示
            self.question = edited_question
            self.init_ui()
    
    def delete_question(self):
        """删除题目"""
        reply = QMessageBox.question(
            self, "确认删除",
            "确定要删除这道题目吗？",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
            QMessageBox.StandardButton.No
        )
        
        if reply == QMessageBox.StandardButton.Yes:
            # 删除题目
            self.question_bank.delete_question(self.question)
            self.close() 